using System;
using System.Collections.Generic;
using System.Linq;
using Xunit;
using Xunit.Abstractions;
using muduoDotNet;
using muduoDotNet.Messages;
using Google.Protobuf;

namespace muduoDotNet.Tests
{
    public class ProtobufMessageHandlerTest
    {
        private readonly ITestOutputHelper _output;
        private readonly ProtobufMessageHandler _handler;

        public ProtobufMessageHandlerTest(ITestOutputHelper output)
        {
            _output = output;
            _handler = new ProtobufMessageHandler();
        }

        [Fact]
        public void TestRegisterMessageType()
        {
            _output.WriteLine("TestRegisterMessageType started");
            
            // 验证内置消息类型已注册
            var registeredTypes = _handler.GetRegisteredMessageTypes().ToList();
            
            Assert.Contains(typeof(EchoRequest), registeredTypes);
            Assert.Contains(typeof(EchoResponse), registeredTypes);
            Assert.Contains(typeof(StatusMessage), registeredTypes);
            Assert.Contains(typeof(Heartbeat), registeredTypes);
            Assert.Contains(typeof(DataPacket), registeredTypes);
            Assert.Contains(typeof(ConnectionInfo), registeredTypes);
            Assert.Contains(typeof(DisconnectRequest), registeredTypes);
            
            _output.WriteLine($"Registered message types count: {registeredTypes.Count}");
        }

        [Fact]
        public void TestGetMessageType()
        {
            _output.WriteLine("TestGetMessageType started");
            
            // 测试已注册的消息类型
            var echoRequestType = _handler.GetMessageType("EchoRequest");
            Assert.Equal(typeof(EchoRequest), echoRequestType);
            
            var statusMessageType = _handler.GetMessageType("StatusMessage");
            Assert.Equal(typeof(StatusMessage), statusMessageType);
            
            // 测试未注册的消息类型
            var unknownType = _handler.GetMessageType("UnknownMessage");
            Assert.Null(unknownType);
            
            _output.WriteLine("GetMessageType tests passed");
        }

        [Fact]
        public void TestSetMessageCallback()
        {
            _output.WriteLine("TestSetMessageCallback started");
            
            bool callbackInvoked = false;
            EchoRequest? receivedMessage = null;
            TcpConnection? receivedConnection = null;
            
            // 设置回调
            _handler.SetMessageCallback<EchoRequest>((conn, msg) =>
            {
                callbackInvoked = true;
                receivedMessage = msg;
                receivedConnection = conn;
            });
            
            // 创建模拟连接和消息
            var loop = new EventLoop();
            var socket = new System.Net.Sockets.Socket(System.Net.Sockets.AddressFamily.InterNetwork, 
                                                      System.Net.Sockets.SocketType.Stream, 
                                                      System.Net.Sockets.ProtocolType.Tcp);
            var connection = new TcpConnection(loop, "test-connection", socket);
            
            var testMessage = new EchoRequest
            {
                Message = "Test callback message",
                ClientId = "test-client",
                Timestamp = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds()
            };
            
            // 调用处理器
            _handler.HandleMessage(connection, testMessage);
            
            // 验证回调被调用
            Assert.True(callbackInvoked);
            Assert.NotNull(receivedMessage);
            Assert.Equal(testMessage.Message, receivedMessage.Message);
            Assert.Equal(testMessage.ClientId, receivedMessage.ClientId);
            Assert.Equal(connection, receivedConnection);
            
            // 清理
            connection.Dispose();
            loop.Dispose();
            
            _output.WriteLine("SetMessageCallback test passed");
        }

        [Fact]
        public void TestRemoveMessageCallback()
        {
            _output.WriteLine("TestRemoveMessageCallback started");
            
            bool callbackInvoked = false;
            
            // 设置回调
            _handler.SetMessageCallback<EchoRequest>((conn, msg) =>
            {
                callbackInvoked = true;
            });
            
            // 移除回调
            _handler.RemoveMessageCallback<EchoRequest>();
            
            // 创建模拟连接和消息
            var loop = new EventLoop();
            var socket = new System.Net.Sockets.Socket(System.Net.Sockets.AddressFamily.InterNetwork, 
                                                      System.Net.Sockets.SocketType.Stream, 
                                                      System.Net.Sockets.ProtocolType.Tcp);
            var connection = new TcpConnection(loop, "test-connection", socket);
            
            var testMessage = new EchoRequest
            {
                Message = "Test remove callback",
                ClientId = "test-client",
                Timestamp = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds()
            };
            
            // 调用处理器（回调应该不被调用）
            _handler.HandleMessage(connection, testMessage);
            
            // 验证回调没有被调用
            Assert.False(callbackInvoked);
            
            // 清理
            connection.Dispose();
            loop.Dispose();
            
            _output.WriteLine("RemoveMessageCallback test passed");
        }

        [Fact]
        public void TestMultipleMessageCallbacks()
        {
            _output.WriteLine("TestMultipleMessageCallbacks started");
            
            bool echoCallbackInvoked = false;
            bool statusCallbackInvoked = false;
            
            // 设置多个消息类型的回调
            _handler.SetMessageCallback<EchoRequest>((conn, msg) =>
            {
                echoCallbackInvoked = true;
            });
            
            _handler.SetMessageCallback<StatusMessage>((conn, msg) =>
            {
                statusCallbackInvoked = true;
            });
            
            // 创建模拟连接
            var loop = new EventLoop();
            var socket = new System.Net.Sockets.Socket(System.Net.Sockets.AddressFamily.InterNetwork, 
                                                      System.Net.Sockets.SocketType.Stream, 
                                                      System.Net.Sockets.ProtocolType.Tcp);
            var connection = new TcpConnection(loop, "test-connection", socket);
            
            // 处理EchoRequest
            var echoMessage = new EchoRequest { Message = "Test echo" };
            _handler.HandleMessage(connection, echoMessage);
            Assert.True(echoCallbackInvoked);
            Assert.False(statusCallbackInvoked);
            
            // 重置标志
            echoCallbackInvoked = false;
            
            // 处理StatusMessage
            var statusMessage = new StatusMessage 
            { 
                Type = StatusMessage.Types.StatusType.Info, 
                Message = "Test status" 
            };
            _handler.HandleMessage(connection, statusMessage);
            Assert.False(echoCallbackInvoked);
            Assert.True(statusCallbackInvoked);
            
            // 清理
            connection.Dispose();
            loop.Dispose();
            
            _output.WriteLine("MultipleMessageCallbacks test passed");
        }

        [Fact]
        public void TestHandleUnknownMessageType()
        {
            _output.WriteLine("TestHandleUnknownMessageType started");
            
            // 创建一个自定义消息类型（未注册回调）
            var heartbeat = new Heartbeat
            {
                Timestamp = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(),
                NodeId = "test-node"
            };
            
            // 创建模拟连接
            var loop = new EventLoop();
            var socket = new System.Net.Sockets.Socket(System.Net.Sockets.AddressFamily.InterNetwork, 
                                                      System.Net.Sockets.SocketType.Stream, 
                                                      System.Net.Sockets.ProtocolType.Tcp);
            var connection = new TcpConnection(loop, "test-connection", socket);
            
            // 处理未注册回调的消息（应该不会抛出异常）
            try
            {
                _handler.HandleMessage(connection, heartbeat);
                _output.WriteLine("Successfully handled unknown message type without callback");
            }
            catch (Exception ex)
            {
                Assert.True(false, $"Should not throw exception for unknown message type: {ex.Message}");
            }
            
            // 清理
            connection.Dispose();
            loop.Dispose();
            
            _output.WriteLine("HandleUnknownMessageType test passed");
        }

        [Fact]
        public void TestCallbackException()
        {
            _output.WriteLine("TestCallbackException started");
            
            // 设置一个会抛出异常的回调
            _handler.SetMessageCallback<EchoRequest>((conn, msg) =>
            {
                throw new InvalidOperationException("Test callback exception");
            });
            
            // 创建模拟连接和消息
            var loop = new EventLoop();
            var socket = new System.Net.Sockets.Socket(System.Net.Sockets.AddressFamily.InterNetwork, 
                                                      System.Net.Sockets.SocketType.Stream, 
                                                      System.Net.Sockets.ProtocolType.Tcp);
            var connection = new TcpConnection(loop, "test-connection", socket);
            
            var testMessage = new EchoRequest
            {
                Message = "Exception test message",
                ClientId = "test-client",
                Timestamp = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds()
            };
            
            // 调用处理器（应该捕获异常而不崩溃）
            try
            {
                _handler.HandleMessage(connection, testMessage);
                _output.WriteLine("Successfully handled callback exception");
            }
            catch (Exception ex)
            {
                Assert.True(false, $"Handler should catch callback exceptions: {ex.Message}");
            }
            
            // 清理
            connection.Dispose();
            loop.Dispose();
            
            _output.WriteLine("CallbackException test passed");
        }
    }
}